﻿// -----------------------------------------------------------------------
// Copyright (c) Microsoft Corporation.  All rights reserved.
// -----------------------------------------------------------------------
using System;
using System.Collections.Generic;
using System.ComponentModel.Composition.AttributedModel;
using System.ComponentModel.Composition.Primitives;
using System.ComponentModel.Composition.ReflectionModel;
using System.Linq.Expressions;
using System.Reflection;
using Microsoft.Internal;

namespace System.ComponentModel.Composition.Caching.AttributedModel
{
    internal class CachedAttributedImportDefinition : ContractBasedImportDefinition
    {
        public CachedAttributedImportDefinition(IDictionary<string, object> cache)
        {
            Assumes.NotNull(cache);
            this.Cache = cache;
        }

        public IDictionary<string, object> Cache
        {
            get;
            private set;
        }

        public override string ContractName
        {
            get { return this.Cache.ReadValue<string>(AttributedCacheServices.CacheKeys.ContractName); }
        }

        public override ImportCardinality Cardinality
        {
            get { return this.Cache.ReadValue<ImportCardinality>(AttributedCacheServices.CacheKeys.Cardinality); }
        }

        public override bool IsPrerequisite
        {
            get { return this.Cache.ReadValue<bool>(AttributedCacheServices.CacheKeys.IsPrerequisite, false); }
        }

        public override bool IsRecomposable
        {
            get { return this.Cache.ReadValue<bool>(AttributedCacheServices.CacheKeys.IsRecomposable, false); }
        }

        public override IEnumerable<string> RequiredMetadata
        {
            get { return this.Cache.ReadEnumerable<string>(AttributedCacheServices.CacheKeys.RequiredMetadata); }
        }

        public override CreationPolicy RequiredCreationPolicy
        {
            get { return this.Cache.ReadValue<CreationPolicy>(AttributedCacheServices.CacheKeys.RequiredCreationPolicy, CreationPolicy.Any); }
        }

        internal ReflectionWritableMember GetMember(Type defaultType)
        {
            return (ReflectionWritableMember)this.Cache.LoadReflectionMember(defaultType);            
        }

        internal ReflectionParameter GetParameter(ConstructorInfo constructor)
        {
            return this.Cache.LoadReflectionParameter(constructor);
        }

        public ImportingItem ToImportingItem(Func<ConstructorInfo> constructor, Type defaultType)
        {
            ReflectionWritableMember member = GetMember(defaultType);
            if (member != null)
            {
                return new ImportingMember(this, member);
            }

            ReflectionParameter parameter = GetParameter(constructor());
            return new ImportingParameter(this, parameter);
        }

        public static IDictionary<string, object> CreateCache(AttributedImportDefinition definition)
        {
            Assumes.NotNull(definition);

            IDictionary<string, object> cache = new Dictionary<string, object>();
            cache.WriteValue(AttributedCacheServices.CacheKeys.ContractName, definition.ContractName);
            cache.WriteValue(AttributedCacheServices.CacheKeys.Cardinality, definition.Cardinality);
            cache.WriteValue(AttributedCacheServices.CacheKeys.IsPrerequisite, definition.IsPrerequisite, false);
            cache.WriteValue(AttributedCacheServices.CacheKeys.IsRecomposable, definition.IsRecomposable, false);
            cache.WriteEnumerable(AttributedCacheServices.CacheKeys.RequiredMetadata, definition.RequiredMetadata);
            cache.WriteValue(AttributedCacheServices.CacheKeys.RequiredCreationPolicy, definition.RequiredCreationPolicy, CreationPolicy.Any);
            cache.WriteReflectionItem(definition.Item, definition.Definition.PartType);

            return cache;
        }
    }
}
